﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using Budjelar.Model.Entities;

namespace Budjelar.Repository.EF
{
    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly BudjelarDbContext m_Context = new BudjelarDbContext();

        public IQueryable<T> AsQueryable()
        {
            return m_Context.Set<T>();
        }

        public IEnumerable<T> Find(Expression<Func<T, bool>> @where)
        {
            return m_Context.Set<T>().Where(@where);
        }

        public T First()
        {
            return m_Context.Set<T>().FirstOrDefault();
        }

        public T First(Expression<Func<T, bool>> @where)
        {
            return m_Context.Set<T>().FirstOrDefault(@where);
        }

        public IEnumerable<T> GetAll()
        {
            return m_Context.Set<T>();
        }

        public void Save(T entity)
        {
            m_Context.Set<T>().Add(entity);
            foreach (var entry in m_Context.ChangeTracker.Entries<Entity>())
            {
                var e = entry.Entity;
                entry.State = ConvertState(e.State);
            }
            m_Context.SaveChanges();
        }

        private EntityState ConvertState(State state)
        {
            switch (state)
            {
                case State.Added:
                    return EntityState.Added;
                case State.Modified:
                    return EntityState.Modified;
                case State.Unchanged:
                    return EntityState.Unchanged;
                case State.Deleted:
                    return EntityState.Deleted;
                default:
                    throw new InvalidOperationException("Unknown state");
            }
        }

        public T Single()
        {
            return m_Context.Set<T>().SingleOrDefault();
        }

        public T Single(Expression<Func<T, bool>> @where)
        {
            return m_Context.Set<T>().SingleOrDefault(@where);
        }
    }
}